#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# chkconfig: - 90 10
# description: Apache Traffic Server is a fast, scalable and extensible  \
#             HTTP/1.1 compliant caching proxy server.
# processname: traffic_cop traffic_manager traffic_server
# config: /etc/trafficserver
# config: /etc/sysconfig/trafficserver
# pidfile: /var/run/trafficserver/cop.pid
#
# Template from /etc/init.d/skeleton on Ubuntu
#
### BEGIN INIT INFO
# Provides:          Traffic Server
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: Startup/shutdown script for the Apache Traffic Server
# Description:       Apache Traffic Server is fast, scalable and extensible
#                    HTTP/1.1 compliant caching proxy server.
### END INIT INFO

# Fedora:
#  When this file is installed as /etc/rc.d/init.d/trafficserver
#  and added to the chkconfig system with `chkconfig --add trafficserver`
#  then the default values of these variables can be overridden
#  in the /etc/sysconfig/trafficserver file
# Ubuntu:
#  Values read from /etc/default/trafficserver

TS_PACKAGE_NAME="Apache Traffic Server"
TS_PACKAGE_VERSION="4.0.1"
TS_PACKAGE_BUGREPORT="dev@trafficserver.apache.org"
UNAME_S=$(uname -s)

if [ -e /etc/SuSE-release ]; then
    DISTRIB_ID="suse"
elif [ -e /etc/fedora-release ]; then
    DISTRIB_ID="fedora"
elif [ -e /etc/redhat-release ]; then
    DISTRIB_ID="redhat" # also exists on Fedora
elif [ -e /etc/lsb-release ]; then
    DISTRIB_ID="ubuntu"
elif [ -e /etc/debian_version ]; then
    DISTRIB_ID="debian" # also exists on Ubuntu
elif [ -e /etc/slackware-version ]; then
    DISTRIB_ID="slackware"
elif [ "$UNAME_S" = "Darwin" ]; then
    DISTRIB_ID="Darwin"
elif [ "$UNAME_S" = "FreeBSD" ]; then
    DISTRIB_ID="FreeBSD"
fi

# We might want to move over to use /etc/system-release for more distros?
# I know at least Fedora supports it as well.
if [ "" = "$DISTRIB_ID" -a -e /etc/system-release ]; then
    case $(cat /etc/system-release) in
	*Amazon*)
	    DISTRIB_ID="redhat" # Amazon AMI is mostly like RHEL
	    ;;
	*)
	    ;;
    esac
fi

# /usr/bin/lsb_release -rd # Ubuntu release & description info

HEAD=/usr/bin/head
test -x $HEAD || HEAD=head
ESED=/usr/bin/sed
test -x $ESED || ESED=sed

# Ubuntu: Do NOT "set -e"

#Ubuntu:PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/usr/sbin:/usr/bin:/sbin:/bin
DESC="start/stop Traffic Server"
NAME=trafficserver
SLEEP_TIME=5
TS_PREFIX="/usr"

TS_ROOT=${TS_ROOT:-$TS_PREFIX}
# TS_BASE is offset inside the file system from where the layout starts
# For standard installations TS_BASE will be empty
eval TS_BASE="`echo $TS_ROOT | ${ESED} -e 's;/usr$;;'`"

TC_NAME=${TC_NAME:-traffic_cop}
TM_NAME=${TM_NAME:-traffic_manager}
TS_NAME=${TS_NAME:-traffic_server}
TL_NAME=${TL_NAME:-traffic_line}
TC_DAEMON=${TC_DAEMON:-$TS_BASE/usr/bin/traffic_cop}
TC_DAEMON_ARGS=""
TM_DAEMON=${TM_DAEMON:-$TS_BASE/usr/bin/traffic_manager}
TM_DAEMON_ARGS=""
TS_DAEMON=${TS_DAEMON:-$TS_BASE/usr/bin/traffic_server}
TS_DAEMON_ARGS=""
TC_PIDFILE=${TC_PIDFILE:-$TS_BASE/var/run/trafficserver/cop.lock}
TM_PIDFILE=${TM_PIDFILE:-$TS_BASE/var/run/trafficserver/manager.lock}
TS_PIDFILE=${TS_PIDFILE:-$TS_BASE/var/run/trafficserver/server.lock}
# number of times to retry check on pid lock file
PIDFILE_CHECK_RETRIES=${PIDFILE_CHECK_RETRIES:-30}
# stdout file of executable
STDOUTLOG=${STDOUTLOG:-$TS_BASE/var/log/trafficserver/traffic_server.stdout}
# stderr file of executable
STDERRLOG=${STDERRLOG:-$TS_BASE/var/log/trafficserver/traffic_server.stderr}

if [ -d /etc/rc.d/init.d ]; then
    SCRIPTNAME=/etc/rc.d/init.d/$NAME # Fedora
elif [ -d /etc/init.d ]; then
    SCRIPTNAME=/etc/init.d/$NAME # Ubuntu
elif [ "$DISTRIB_ID" = "Darwin" ]; then
    SCRIPTNAME=$0 # Darwin
elif [ "$DISTRIB_ID" = "FreeBSD" ]; then
    SCRIPTNAME=$0 # FreeBSD 
else
    echo "This script needs to be ported to this OS"
    exit 1
fi

# Exit if the package can not be found
if [ ! -x "$TS_DAEMON" ]; then
    echo "Error: Can not find $TS_DAEMON using TS_ROOT=$TS_ROOT"
    echo "       Please set TS_ROOT to point to base installation."
    exit 0
fi

# Ubuntu: Read configuration variable file if it is present
test -r /etc/default/$NAME && . /etc/default/$NAME

# RHEL/Fedora: Read configuration variable file if it is present
test -r /etc/sysconfig/$NAME && . /etc/sysconfig/$NAME

# Ubuntu: Load the VERBOSE setting and other rcS variables
test -f /etc/default/rcS && . /etc/default/rcS

# Suse: load rc.status
test -f /etc/rc.status && . /etc/rc.status

# Fedora: make avail helper functions 'action', 'killproc', 'status', etc
test -f /etc/rc.d/init.d/functions && . /etc/rc.d/init.d/functions

# Ubuntu: Define LSB log_* functions.
#         Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
test -f /lib/lsb/init-functions && . /lib/lsb/init-functions

# FreeBSD
# NB: FreeBSD's ports system installs a run script in /usr/local/etc/rc.d/ 
# with native OS rc.subr(8) features.
test -f /etc/rc.subr && . /etc/rc.subr

if [ ! -d /var/run/trafficserver ]
then
	mkdir -p /var/run/trafficserver
	chown ats:ats /var/run/trafficserver
fi

#
# Fedora:
#  launches $* in the background
#  and checks if program creates its own pid lock file
#  redirects stdout and stderr to files
#  this function is meant to substitute 'daemon'
#  because 'daemon' expects $1 to fork itself
forkdaemon()
{
    local i=0

    # launch in background, i.e. fork
    # and redirect stdout and stderr to files
    $* >> $STDOUTLOG 2>> $STDERRLOG &

    while (( $i < $PIDFILE_CHECK_RETRIES ))
    do
        # check for regular file and size greater than 0
        if [[ -f $TC_PIDFILE ]] && [[ -s $TC_PIDFILE ]]
        then
            success
            return 0
        fi

        sleep 1  # zzz for 1 second
        (( i++ ))

    done

    failure
    return 1
}

[ -f /etc/sysconfig/custom.trafficserver ] && . /etc/sysconfig/custom.trafficserver

#
# Ubuntu: Function that starts the daemon/service
#
do_start()
{
  # Return
  #   0 if daemon has been started
  #   1 if daemon was already running
  #   2 if daemon could not be started
    start-stop-daemon --start --quiet --pidfile $TC_PIDFILE --exec $TC_DAEMON --test > /dev/null \
        || return 1
    start-stop-daemon --start --background --quiet --pidfile $TC_PIDFILE --exec $TC_DAEMON -- \
        $TC_DAEMON_ARGS \
        || return 2
  # Add code here, if necessary, that waits for the process to be ready
  # to handle requests from services started subsequently which depend
  # on this one.  As a last resort, sleep for some time.
    sleep 1
    test -f "$TC_PIDFILE" || return 2
}

#
# Ubuntu: Function that stops the daemon/service
#
do_stop()
{
  # Return
  #   0 if daemon has been stopped
  #   1 if daemon was already stopped
  #   2 if daemon could not be stopped
  #   other if a failure occurred
    start-stop-daemon --stop --quiet --retry=QUIT/30/KILL/5 --pidfile $TC_PIDFILE --name $TC_NAME
    RETVAL="$?"
    test "$RETVAL" != 0 && return $RETVAL
  # Wait for children to finish too if this is a daemon that forks
  # and if the daemon is only ever run from this initscript.
  # If the above conditions are not satisfied then add some other code
  # that waits for the process to drop all resources that could be
  # needed by services started subsequently.  A last resort is to
  # sleep for some time.
    start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $TC_DAEMON
    RETVAL="$?"
    test "$RETVAL" != 0 && return $RETVAL
  # Need to stop the TM and TS also
    start-stop-daemon --stop --quiet --oknodo --retry=QUIT/30/KILL/5 --pidfile $TM_PIDFILE --name $TM_NAME
    RETVAL="$?"
    test "$RETVAL" != 0 && return $RETVAL
    start-stop-daemon --stop --quiet --oknodo --retry=QUIT/30/KILL/5 --pidfile $TS_PIDFILE --name $TS_NAME
    RETVAL="$?"
    test "$RETVAL" != 0 && return $RETVAL
  # Many daemons don't delete their pidfiles when they exit.
    rm -f $TC_PIDFILE
    rm -f $TM_PIDFILE
    rm -f $TS_PIDFILE
    return "$RETVAL"
}

# main
case "$1" in
    start)
        if [ "$DISTRIB_ID" = "ubuntu" -o "$DISTRIB_ID" = "debian" ] ; then
            test "x$VERBOSE" != "xno" && log_daemon_msg "Starting $DESC" "$NAME"
            retval=0
            do_start
            test "$?" -ne 0 -a "$?" -ne 1 && retval=1
            test "x$VERBOSE" != "xno" && log_daemon_msg "$retval"
            exit "$retval"
        elif [ "$DISTRIB_ID" = "fedora" -o "$DISTRIB_ID" = "redhat" ]; then
            action "Starting ${TS_PACKAGE_NAME}:" forkdaemon $TC_DAEMON $TC_DAEMON_ARGS
        elif [ "$DISTRIB_ID" = "suse" ]; then
            echo -n "Starting ${TS_PACKAGE_NAME}"
            startproc -p $TC_PIDFILE $TC_DAEMON $TC_DAEMON_ARGS
            rc_status -v
        elif [ "$DISTRIB_ID" = "Darwin" ]; then
            echo "Starting ${TS_PACKAGE_NAME}"
            launchctl list $TC_NAME > /dev/null 2>&1 && exit 0
            launchctl submit -l $TC_NAME -p $TC_DAEMON -o $STDOUTLOG -e $STDERRLOG -- $TC_DAEMON_ARGS
        elif [ "$DISTRIB_ID" = "FreeBSD" ]; then
            echo "Starting ${TS_PACKAGE_NAME}"
            name="$TC_NAME"
            command="/usr/sbin/daemon"
            command_args="$TC_DAEMON $TC_DAEMON_ARGS"
            pidfile="$TC_PIDFILE"
            run_rc_command "$1"
        else
            echo "This script needs to be ported to this OS"
            exit 1
        fi
        ;;
    stop)
        if [ "$DISTRIB_ID" = "ubuntu" -o "$DISTRIB_ID" = "debian" ] ; then
            test "x$VERBOSE" != "xno" && log_daemon_msg "Stopping $DESC" "$NAME"
            retval=0
            do_stop
            test "$?" -ne 0 -a "$?" -ne 1 && retval=1
            test "x$VERBOSE" != "xno" && log_daemon_msg "$retval"
            exit "$retval"
        elif [ "$DISTRIB_ID" = "fedora" -o "$DISTRIB_ID" = "redhat" ]; then
            action "Stopping ${TC_NAME}:" killproc -p $TC_PIDFILE $TC_DAEMON
            action "Stopping ${TM_NAME}:" killproc -p $TM_PIDFILE $TM_DAEMON
            action "Stopping ${TS_NAME}:" killproc -p $TS_PIDFILE $TS_DAEMON
        elif [ "$DISTRIB_ID" = "suse" ]; then
            echo -n "Stopping ${TC_NAME}"
            killproc -p $TC_PIDFILE $TC_DAEMON
            rc_status -v
            echo -n "Stopping ${TM_NAME}"
            killproc -p $TM_PIDFILE $TM_DAEMON
            rc_status -v
            echo -n "Stopping ${TS_NAME}"
            killproc -p $TS_PIDFILE $TS_DAEMON
            rc_status -v
        elif [ "$DISTRIB_ID" = "Darwin" ]; then
            echo "Stopping ${TS_PACKAGE_NAME}"
            launchctl list $TC_NAME > /dev/null 2>&1 || exit 0
            echo "Stopping ${TC_NAME}"
            launchctl remove ${TC_NAME}
            rm -f ${TC_PIDFILE}
            echo "Stopping ${TM_NAME}"
            kill $(cat $TM_PIDFILE)
            rm -f ${TM_PIDFILE}
            echo "Stopping ${TS_NAME}"
            kill $(cat $TS_PIDFILE)
            rm -f ${TS_PIDFILE}
        elif [ "$DISTRIB_ID" = "FreeBSD" ]; then
            echo "Stopping ${TS_PACKAGE_NAME}"
            if [ -e "$TC_PIDFILE" ]; then 
                kill $(cat $TC_PIDFILE)
                rm -f ${TC_PIDFILE}
            fi
            if [ -e "$TM_PIDFILE" ]; then 
                kill $(cat $TM_PIDFILE)
                rm -f ${TM_PIDFILE}
            fi
        else
            echo "This script needs to be ported to this OS"
            exit 1
        fi
        ;;
    reload|force-reload)
        if [ "$DISTRIB_ID" = "ubuntu" -o "$DISTRIB_ID" = "debian" ] ; then
            test "x$VERBOSE" != "xno" && log_daemon_msg "Reloading ${NAME}:"
            retval=0
            $TL_NAME -x
            test "$?" -ne 0 -a "$?" -ne 1 && retval=1
            test "x$VERBOSE" != "xno" && log_daemon_msg "$retval"
            exit "$retval"
        elif [ "$DISTRIB_ID" = "fedora" -o "$DISTRIB_ID" = "redhat" ]; then
            action "Reloading ${NAME}:" $TL_NAME -x
        elif [ "$DISTRIB_ID" = "suse" ]; then
            echo -n "Reloading ${NAME}"
            $TL_NAME -x
            rc_status -v
        elif [ "$DISTRIB_ID" = "Darwin" ]; then
            echo "Reloading ${NAME}"
            $TL_NAME -x
        elif [ "$DISTRIB_ID" = "FreeBSD" ]; then
            echo "Reloading ${NAME}"
            $TL_NAME -x
        else
            echo "This script needs to be ported to this OS"
            exit 1
        fi
        ;;
    restart)
        if [ "$DISTRIB_ID" = "ubuntu" -o "$DISTRIB_ID" = "debian" ] ; then
      #
      # If the "reload" option is implemented then remove the
      # 'force-reload' alias
      #
            log_daemon_msg "Restarting $DESC" "$NAME"
            do_stop
            case "$?" in
                0|1)
                    sleep $SLEEP_TIME
                    do_start
                    case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 0 ;; # Daemons were already stopped
                        *) log_end_msg 1 ;; # Failed to start
                    esac
                    ;;
                *)
            # Failed to stop
                    log_end_msg 1
                    ;;
            esac
        else
      # This is the typical process for restart
            sh $0 'stop'
            sleep $SLEEP_TIME
            sh $0 'start'
        fi
        ;;
    status)
        if [ "$DISTRIB_ID" = "fedora" -o "$DISTRIB_ID" = "redhat" ]; then
            status -p $TC_PIDFILE $TC_NAME
        elif [  "$DISTRIB_ID" = "suse" ]; then
            echo -n "Checking for service ${DM}: "
            checkproc -p $TC_PIDFILE $TC_NAME
            rc_status -v
        elif [ "$DISTRIB_ID" = "Darwin" ]; then
            /bin/echo -n "${TS_PACKAGE_NAME} is "
            launchctl list $TC_NAME > /dev/null 2>&1
            status=$?
            [ $status -eq 0 ] || /bin/echo -n "not "
            echo "running."
        elif [ "$DISTRIB_ID" = "FreeBSD" ]; then
            if pgrep $TM_NAME > /dev/null ; then 
                echo "$TM_NAME running as pid `cat $TM_PIDFILE`" ; else 
                echo "$TM_NAME not running" 
            fi
            if pgrep $TS_NAME > /dev/null ; then 
                echo "$TS_NAME running as pid `cat $TS_PIDFILE`"; else 
                echo "$TS_NAME not running" 
            fi
            if pgrep $TC_NAME > /dev/null ; then 
                echo "$TC_NAME running as pid `cat $TC_PIDFILE`"; else 
                echo "$TC_NAME not running" ; 
            fi
            exit $status
        else
            echo "This script needs to be ported to this OS"
            exit 1
        fi
        ;;
    condrestart)
        if [ "$DISTRIB_ID" = "fedora" -o "$DISTRIB_ID" = "redhat" ]; then
            if $0 'status'
            then
                sh $0 'stop'
                sh $0 'start'
            fi
        else
            echo "This script needs to be ported to this OS"
            exit 1
        fi
        ;;
    *)
        if [ "$DISTRIB_ID" = "ubuntu" -o "$DISTRIB_ID" = "debian" ] ; then
            echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
        elif [ "$DISTRIB_ID" = "fedora" -o "$DISTRIB_ID" = "redhat" ]; then
            echo "Usage: $0 {start|stop|status|restart|condrestart}"
        elif [ "$DISTRIB_ID" = "suse" ]; then
            echo "Usage: $0 {start|stop|restart|status}"
        elif [ "$DISTRIB_ID" = "Darwin" ]; then
            echo "Usage: $0 {start|stop|restart|status}"
        elif [ "$DISTRIB_ID" = "FreeBSD" ]; then
            echo "Usage: $0 Usage: (start|stop|restart|status)"
            echo "NB: FreeBSD's ports system installs a rc script in"
            echo "/usr/local/etc/rc.d/ with native rc.subr(8) features."
        else
            echo "This script needs to be ported to this OS"
            exit 1
        fi
        exit 3
        ;;
esac
